<?php
/***************************************************************
*  Copyright notice
*  (c) 2009, jianyuzhu@gmail.com
*  All rights reserved
*  This script is part of the PPEMI project.
***************************************************************/

class LibTransport {
	var $time_limit = -1;
	var $connect_timeout = -1;
	var $stream_timeout = -1;
	
	var $request_type = 'curl';//curl, socket
	var $request_url = '';
	var $request_params = '';
	var $request_method = 'POST';//POST, GET
	var $request_headers = '';
	
	//constructor
	function LibTransport($time_limit = -1, $connect_timeout = -1, $stream_timeout = -1, $request_type = 'curl') {
		$this->time_limit = $time_limit;
		$this->connect_timeout = $connect_timeout;
		$this->stream_timeout = $stream_timeout;
		$this->request_type = $request_type;
	}
	
	function setRequestType($request_type) {
		$this->request_type = $request_type;
	}
	
	//methods
	function request($url, $params = '', $method = 'POST', $headers = '') {
		$fsock_exists = function_exists('fsocket');
		$curl_exists = function_exists('curl_init');
		
		if( !$fsock_exists && !$curl_exists ) {
			die('NO FUNCTION');
		}
		
		if( !$url ) {
			die('INVALID URL');
		}
		
		if( $this->time_limit > -1 ) {
			set_time_limit($this->time_limit);
		}
		
		$method = (($method === 'GET') ? $method : 'POST');
		$response = '';
		$temp = '';
		
		if( $params && is_array($params) ) {
			foreach($params as $k => $v) {
				$temp .= '&' . $k . '=' . $v;
			}
			$params = preg_replace('/^&', '', $temp);
		}
		
		if( $fsock_exists && !$this->use_curl ) {
			$response = $this->request_socket($url, $params, $method, $headers);
		} elseif( $curl_exists ) {
			$response = $this->request_curl($url, $params, $method, $headers);
		}
		
		if( !$response ) {
			return false;
		}
		
		return $response;
	}
	
	//
	function request_socket($url, $params, $method, $headers) {
		$query = $auth = $content_type = $content_length = $request_body = $request = $http_response = $temp = '';
		$error = $errstr = '';
		$crlf = $this->crlf();
		
		if( $method === 'GET' ) {
			$query .= $params ? '?' . $params : '';
		} else {
			$request_body = $params;
			$content_type = 'Content-Type: application/x-www-form-urlencoded' . $crlf;
			$content_length = 'Content-Length: ' . strlen($request_body) . $crlf . $crlf;
		}
		
		$url_parts = $this->parse_raw_url($url);
		$path = $url_parts['path'] . $query;
		
		if( !empty($url_parts['user']) ) {
			$auth = 'Authorization: Basic ' . base64_encode($url_parts['user'] . ':' . $url_parts['pass']) . $crlf;
		}
		
		if( $headers && is_array($headers) ) {
			foreach($headers as $k => $v) {
				$temp .= $k . ': ' . $v . $crlf;
			}
			$headers = $temp;
		}
		
		$request = $method . $path . ' HTTP/1.0' . $crlf 
				. 'Host: ' . $url_parts['host'] . $crlf 
				. $auth 
				. $headers 
				. $content_type 
				. $content_length 
				. $request_body;
		
		if( $this->connect_timeout > -1 ) {
			$fp = @fsockopen($url_parts['host'], $url_parts['port'], $error, $errstr, $connect_timeout);
		} else {
			$fp = @fsockopen($url_parts['host'], $url_parts['port'], $error, $errstr);
		}
		
		if( !$fp ) {
			return false;
		}
		
		if( !@fwrite($fp, $request) ) {
			return false;
		}
		
		while(!feof($fp)) {
			$http_response .= fgets($fp);
		}
		@fclose($fp);
		
		if( !$http_response ) {
			return false;
		}
		
		$pattern = '/\r\n\r\n|\n\n|\r\r/';
		list($http_header, $http_body) = preg_split($pattern, $http_response, 2);
		$http_response = array('header' => $http_header, 'body' => $http_body);
		
		return $http_response;
	}
	
	//
	function request_curl($url, $params, $method, $headers) {
		$ch = curl_init();
		
		curl_setopt($ch, CURLOPT_FORBID_REUSE, true);
		curl_setopt($ch, CURLOPT_HEADER, true);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
		
		$url_parts = $this->parse_raw_url($url);
		
		if( !empty($url_parts['user']) ) {
			$auth = $url_parts['user'] . ':' . $url_parts['pass'];
			curl_setopt($ch, CURLOPT_USERPWD, $auth);
			curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
		}
		
		$http_headers = array();
		$http_headers[] = 'Host: ' . $url_parts['host'];
		
		if( $headers && is_array($headers) ) {
			foreach($headers as $k => $v) {
				$http_headers[] = $k . ': ' . $v;
			}
		}
		
		if( $method === 'GET' ) {
			curl_setopt($ch, CURLOPT_HTTPGET, true);
			$url .= $params ? '?' . $params : '';
		} else {
			curl_setopt($ch, CURLOPT_POST, true);
			$http_headers[] = 'Content-Type: application/x-www-form-urlencoded';
			$http_headers[] = 'Content-Length: ' . strlen($params);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
		}
		
		curl_setopt($ch, CURLOPT_URL, $url);
		curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
		
		if( $this->connect_timeout > -1 ) {
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connect_timeout);
		}
		
		if( $this->stream_timeout > -1 ) {
			curl_setopt($ch, CURLOPT_TIMEOUT, $this->stream_timeout);
		}
		
		$http_response = curl_exec($ch);
		
		if( curl_errno($ch) != 0 ) {
			return false;
		}
		curl_close($ch);
		
		$pattern = '/\r\n\r\n|\n\n|\r\r/';
		list($http_header, $http_body) = preg_split($pattern, $http_response, 2);
		$http_response = array('header' => $http_header, 'body' => $http_body);
		
		return $http_response;
	}	
	
	//private
	function parse_raw_url($raw_url) {
		$v = array();
		$raw_url = (string)$raw_url;
		
		if( strpos($raw_url, '://') === false ) {
			$raw_url = 'http://' . $raw_url;
		}
		
		$v = parse_url($raw_url);
		if( !isset($v['path']) ) {
			$v['path'] = '/';
		}
		if( !isset($v['port']) ) {
			$v['port'] = '80';
		}
		
		return $v;
	}
	
	function crlf() {
		$crlf = '';
		if( strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ) {
			$crlf = "\r\n";
		} elseif( strtoupper(substr(PHP_OS, 0, 3)) === 'MAC' ) {
			$crlf = "\r";
		} else {
			$crlf = "\n";
		}
		
		return $crlf;
	}
}
//
?>